<template>
    <div class="page_root" :key="queryUpdateFlag" data-page-name="产研资源投入" data-page-identification="n_x46qj18uxw">
        <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
            <!-- begin vid_c0o232iia4 自定义模板_fop3v1xggd -->
            <div class="body">
                <div class="top-search">
                    <a-row :gutter="24">
                        <a-col :span="5">
                            <a-form-item :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }" label="时间">
                                <a-range-picker
                                    style="width: 100%"
                                    :value="state.filter.dateList"
                                    value-format="YYYY-MM-DD"
                                    @change="handleDateChange"
                                    :allowClear="false"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="5">
                            <a-form-item :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }" label="迭代项目">
                                <a-select
                                    show-search
                                    :placeholder="selectHolder"
                                    v-model:value="state.filter.projectId"
                                    :options="state.projectTreeDate"
                                    allow-clear
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    @change="getData"
                                />
                            </a-form-item>
                        </a-col>

                        <a-col :span="5">
                            <a-form-item :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }" label="团队成员">
                                <a-select
                                    :placeholder="selectHolder"
                                    show-search
                                    v-model:value="state.filter.user"
                                    :options="state.userList"
                                    allow-clear
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    @change="getData"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="4">
                            <a-space>
                                <a-button @click="resetData" ghost type="primary"> 重置</a-button>
                            </a-space>
                        </a-col>
                    </a-row>
                </div>
                <div class="content">
                    <div class="table-top">
                        <div class="tip-title"> 团队成员列表 </div>
                        <div class="top-right">
                            <div class="color-item">
                                <div>计划进展</div>
                                <div class="doing"></div>
                            </div>
                            <div class="color-item">
                                <div>实际进展正常完成</div>
                                <div class="to-do"></div>
                            </div>
                            <div class="color-item">
                                <div>实际进展延期或延期完成</div>
                                <div class="to-do-daily"></div>
                            </div>
                        </div>
                    </div>
                    <a-spin :spinning="state.tableLoading" tip="数据加载中...">
                        <div class="gantt-container" ref="ganttContainer" style="width: 100%; height: 600px"> </div>
                    </a-spin>
                </div>
            </div>
            <!-- end vid_c0o232iia4 自定义模板_fop3v1xggd -->
        </a-spin>
    </div>
</template>
<script setup lang="tsx">
    import {
        h,
        ref,
        reactive,
        toRaw,
        markRaw,
        watch,
        computed,
        onBeforeMount,
        onMounted,
        onBeforeUnmount,
        onUnmounted,
        onActivated,
        onDeactivated
    } from 'vue'
    import { useRoute, useRouter } from 'vue-router'
    const router = useRouter()
    const route = useRoute()
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios'
    import {
        cloneDeep,
        localGet,
        merge,
        getDifferenceArray,
        traversalTreeStructure,
        checkCaseCondition,
        renderStringInTemplate,
        handleBreadcrumbJump,
        throttle,
        permission,
        getComponentParamsValue
    } from '@/utils/index'
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is'
    import dayjs from 'dayjs'
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart'
    import { message, notification, Modal } from 'ant-design-vue'
    import {
        propertyFormatByNumber,
        propertyFormatByPercentage,
        propertyFormatByDate,
        parseSubFromDataList
    } from '@/utils/format'
    import colorTheme from '@/design/custom-theme.json'

    import UserTableRecords from '@/model/UserTableRecords'
    import { getAppBaseUrl } from '@/utils/index'
    import { sendToken } from '@/hooks/useIframeToken'
    import { useSystemStore } from '@/store/modules/system'
    const systemStore = useSystemStore()

    // 获取传入的流程ID和组件参数
    const props = defineProps({
        'processInstanceId': {
            type: [String, Number, Boolean],
            default: undefined
        }
    })
    const immediateWatch = (source, callback) => {
        watch(source, callback, { deep: true, immediate: true })
    }

    /* -------------------------- 属性定义 -------------------------- */

    const setTimeOutList = []
    const pageLoading = reactive({
        loading: false,
        tip: undefined
    })
    const authInfo = localGet('app-user-store')

    // 处理校验
    const setSubFormName = (parentInfo, name) => {
        return [parentInfo.parents, parentInfo.cycleIndex, name]
    }

    /* ========================== 属性定义 ========================== */

    /* -------------------------- 元素数据引用 -------------------------- */

    /* ========================== 元素数据引用 ========================== */

    /* -------------------------- 页面数据 -------------------------- */

    /* ========================== 页面数据 ========================== */

    /* -------------------------- 响应 -------------------------- */

    /* ========================== 响应 ========================== */

    /* -------------------------- 函数 -------------------------- */

    /* ========================== 函数 ========================== */

    /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId
    })

    /* ========================== 页面参数 ========================== */

    /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================

    /* ========================== 组件事件处理方法 ========================== */

    /* -------------------------- 生命周期 -------------------------- */
    // 用于参数变更后重新执行自定义指令
    const queryUpdateFlag = ref(0)
    onMounted(() => {})

    onUnmounted(() => {
        // 销毁定时器
        setTimeOutList.forEach(({ repeat, timer }) => {
            repeat ? clearInterval(timer) : clearTimeout(timer)
        })
    })

    /* ========================== 生命周期 ========================== */

    /* -------------------------- 数据关联处理 -------------------------- */

    /* -------------------------- 表单数据同步 -------------------------- */
    /* ========================== 表单数据同步 ========================== */

    /* ========================== 数据关联处理 ========================== */

    /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

    /* ========================== 不同组件自定义的处理逻辑 ========================== */

    // ================================定制化逻辑========================================
    import { nextTick } from 'vue'
    import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
    import gantt from 'dhtmlx-gantt'
    const state = reactive({
        filter: {
            role: undefined,
            projectId: undefined,
            milepostName: undefined,
            user: undefined,
            status: undefined,
            dateList: []
        },
        roleList: [],
        projectTreeDate: [],
        userList: [],
        dataSource: [],
        tableHeight: 520,
        areaFactoryList: [],
        tableLoading: false
    })
    onMounted(async () => {
        nextTick(resizeGanttHeight)
        setDefaultDateRange()
        window.addEventListener('resize', resizeGanttHeight)
        initGantt()
        await Promise.all([getData(), getFilter()])
    })

    onUnmounted(() => {
        window.removeEventListener('resize', resizeGanttHeight)
        setTimeOutList.forEach(({ repeat, timer }) => (repeat ? clearInterval(timer) : clearTimeout(timer)))
    })

    // ----------------------------- 甘特图逻辑 -----------------------------
    const ganttContainer = ref(null)

    function initGantt() {
        if (!ganttContainer.value) return
        gantt.clearAll()
        gantt.config = {
            ...gantt.config,
            smart_rendering: false,
            details_on_dblclick: false,
            min_column_width: 60,
            details_on_create: false,
            open_tree_initially: true,
            scale_height: 50,
            row_height: 30,
            sort: true,
            drag_links: false,
            drag_resize: false,
            drag_move: false,
            drag_progress: false,
            autosize: false,
            min_task_height: 20,
            duration_unit: 'day',
            duration_step: 1,
            xml_date: '%Y-%m-%d',
            scroll_size: 15,
            show_errors: false
        }

        // gantt.config.columns = [
        //     { name: 'text', label: '团队成员', width: 220, tree: true, open: true, template: t => tplCell(t.text) },
        //     { name: 'project', label: '迭代项目', width: 150, template: t => tplCell(t.project) },
        //     { name: 'taskName', label: '任务名称', width: 200, template: t => tplCell(t.taskName) }
        // ]
        gantt.config.columns = [
            {
                name: 'text',
                label: '团队成员',
                width: 220,
                tree: true,
                open: true,
                template: t => {
                    if (t.parent === '0' || !t.parent) {
                        // 人员节点
                        return tplCell(t.text)
                    } else {
                        // 计划和实际节点，显示空或特定标识
                        return tplCell('')
                    }
                }
            },
            {
                name: 'project',
                label: '迭代项目',
                width: 150,
                template: t => {
                    // 只在data节点显示项目
                    if (!t.type) {
                        // 人员节点
                        return tplCell(t.project)
                    } else {
                        // 计划和实际节点，显示空或特定标识
                        return tplCell('')
                    }
                }
            },
            {
                name: 'taskName',
                label: '任务名称',
                width: 200,
                template: t => {
                    if (!t.type) {
                        // 人员节点
                        return tplCell(t.taskName)
                    } else if (t.type === '计划') {
                        // 计划和实际节点，显示空或特定标识
                        return tplCell('计划')
                    } else if (t.type === '实际') {
                        // 计划和实际节点，显示空或特定标识
                        return tplCell('实际')
                    } else {
                        // 计划和实际节点，显示空或特定标识
                        return tplCell('')
                    }
                }
            }
            // {
            //     name: 'type',
            //     label: '类型',
            //     width: 80,
            //     template: t => {
            //         if (t.type === '计划') {
            //             return tplCell('计划')
            //         } else if (t.type === '实际') {
            //             return tplCell('实际')
            //         }
            //         return tplCell('')
            //     }
            // }
        ]
        // 修改 scales 配置，在日期后面添加星期几
        gantt.config.scales = [
            { unit: 'month', step: 1, format: '%Y-%m' },
            {
                unit: 'day',
                step: 1,
                format: date => {
                    // 获取日期号
                    const day = gantt.date.date_to_str('%d')(date)
                    // 获取星期几（中文）
                    const weekdays = ['日', '一', '二', '三', '四', '五', '六']
                    const weekday = weekdays[date.getDay()]
                    return `${day}(${weekday})`
                }
            }
        ]

        gantt.templates.task_class = (start, end, task) => {
            // 一级（人员节点）
            if (task.parent === '0' || !task.parent) {
                return 'none-status'
            }

            // 二级（data 节点）
            if (!task.type) {
                return 'none-status'
            }

            // 计划
            if (task.type === '计划') {
                return 'plan-task'
            }

            // 实际，根据 dataMap 判断延迟
            if (task.type === '实际') {
                console.log(task)
                return 'actual-task'
            }

            return ''
        }
        gantt.templates.task_cell_class = function (item, date) {
            // 只对实际任务进行处理
            if (item.type !== '实际') return ''

            const dateStr = gantt.date.date_to_str('%Y-%m-%d')(date)

            // 检查该日期是否在 dataMap 中
            if (item.dataMap && item.dataMap[dateStr]) {
                const dayData = item.dataMap[dateStr]

                // 如果是延期状态，返回红色类名
                if (dayData.actual === 'delay') {
                    return 'delayed-cell'
                }
                // 否则返回正常类名
                return 'normal-cell'
            }

            return ''
        }
        gantt.templates.task_text = () => ''
        gantt.attachEvent('onGanttScroll', syncScroll)
        gantt.init(ganttContainer.value)
    }

    function syncScroll(left, top) {
        const grid = gantt.$grid_data
        const timeline = gantt.$task_data
        if (grid && timeline) {
            grid.scrollTop = top
            timeline.scrollTop = top
        }
    }

    function resizeGanttHeight() {
        const container = ganttContainer.value
        if (!container) return
        const availableHeight = window.innerHeight - container.getBoundingClientRect().top - 40
        container.style.height = `${availableHeight}px`
        gantt.setSizes()
    }

    function tplCell(text?: string) {
        return `<div class="cell-ellipsis" title="${text || ''}">${text || ''}</div>`
    }

    // ----------------------------- 数据获取 -----------------------------
    async function getData() {
        state.tableLoading = true
        try {
            const res = await post('/solution-ppm/api/v2/built-in-system-ppm/platform_resource_dashboard/search', {
                ...state.filter
            })
            if (res.code !== 200) return message.error(res.message)

            state.dataSource = res.data.detailList
            const tasks = convertToGanttData(state.dataSource)
            gantt.clearAll()
            gantt.parse({ data: tasks })
            return tasks
        } finally {
            state.tableLoading = false
        }
    }

    async function getFilter() {
        const res = await post('/solution-ppm/api/v2/built-in-system-ppm/platform_resource_dashboard/search', {
            dateList: state.filter.dateList
        })
        if (res.code !== 200) return message.error(res.message)

        const detailList = res.data.detailList || []
        state.projectTreeDate = uniqueOptions(detailList, 'projectId', 'projectName')
        state.userList = uniqueOptions(detailList, 'user', 'user')
        state.roleList = uniqueOptions(detailList, 'role', 'role')
    }

    function uniqueOptions(list, key, labelKey) {
        return Array.from(
            new Map(list.filter(i => i[key]).map(i => [i[key], { label: i[labelKey], value: i[key] }])).values()
        )
    }

    // ----------------------------- 数据转换 -----------------------------

    function convertToGanttData(list) {
        return list.map(item => ({
            id: item.id,
            text: item.text,
            dataMap: item.dataMap, // 这个很重要，包含了每天的状态
            taskName: item.taskName,
            parent: item.parentId,
            start_date: item.startTime,
            duration: dayjs(item.endTime).diff(dayjs(item.startTime), 'day') + 1,
            user: item.user,
            project: item.projectName,
            role: item.role,
            type: item.type,
            daily: item.daily,
            plan_progress: calcProgress(item.dataMap, 'plan'),
            actual_progress: calcProgress(item.dataMap, 'actual'),
            status: item.taskStatus
        }))
    }

    // 检查任务是否延期
    function checkIfDelayed(dataMap, startTime, endTime) {
        if (!dataMap) return false

        const today = dayjs().format('YYYY-MM-DD')
        const start = dayjs(startTime)
        const end = dayjs(endTime)

        // 检查今天是否在任务时间范围内
        // const isInRange = dayjs(today).isBetween(start, end, null, '[]')
        //
        // if (!isInRange) return false

        // 检查今天及之前的日子是否有延期
        for (let date in dataMap) {
            const day = dayjs(date)
            const todayDay = dayjs(today)

            // 只检查今天及之前的日子
            if (day.isAfter(todayDay)) continue

            if (dataMap[date].actual === 'delay') {
                return true
            }
        }

        return false
    }
    function calcProgress(dataMap, type) {
        if (!dataMap) return 0
        const dates = Object.keys(dataMap)
        if (!dates.length) return 0
        const done = dates.filter(d => dataMap[d]?.[type] && dataMap[d][type] !== 'default').length
        return Math.round((done / dates.length) * 100)
    }

    // ----------------------------- 筛选事件 -----------------------------
    function handleDateChange(dates) {
        if (!dates || dates.length !== 2) return
        const [start, end] = dates
        if (dayjs(end).diff(dayjs(start), 'day') > 60) {
            return message.info('日期范围不能超过 60 天，请重新选择')
        }
        state.filter.dateList = dates
        getData()
        getFilter()
    }

    function resetData() {
        setDefaultDateRange()
        state.filter.projectId = state.filter.role = state.filter.user = undefined
        getData()
    }

    function setDefaultDateRange() {
        const start = dayjs().startOf('month').format('YYYY-MM-DD')
        const end = dayjs().endOf('month').format('YYYY-MM-DD')
        state.filter.dateList = [start, end]
    }

    // ----------------------------- 展开/收起控制 -----------------------------
    let expanded = true
    function toggleExpandTree() {
        expanded ? collapseAll() : expandAll()
        expanded = !expanded
    }
    function expandAll() {
        gantt.eachTask(t => gantt.open(t.id))
    }
    function collapseAll() {
        gantt.eachTask(t => gantt.close(t.id))
    }
</script>
<style lang="less" scoped>
    .page_root {
        width: 100%;
        height: 100%;
        overflow: auto;
    }
    .page_root :deep(.@{ant-prefix}-spin-nested-loading),
    .page_root :deep(.@{ant-prefix}-spin-container) {
        height: 100%;
    }
    .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper) {
        display: flex;
        flex-flow: column nowrap;
        justify-content: flex-start;
    }
    .page_root :deep(.@{ant-prefix}-table) {
        flex: auto;
        overflow: auto;
    }
    .table-moreBtn_down {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        width: 100px;
    }

    .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
        background: #ebf1ff;
    }

    /*  表格树结构样式处理，展开按钮层级增加*/
    :deep(.@{ant-prefix}-table-row-expand-icon) {
        z-index: 1;
    }
    /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
    :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 15px !important;
        width: calc(100% - 15px);
    }
    :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 30px !important;
        width: calc(100% - 30px);
    }
    :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 45px !important;
        width: calc(100% - 45px);
    }
    :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 60px !important;
        width: calc(100% - 60px);
    }

    /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
    :deep(.@{ant-prefix}-transfer-list) {
        height: 100%;
        width: 50%;
    }

    /*
样式*/
    .body {
        height: 100%;
    }
    .top-search {
        background-color: #fff;
        padding: 16px 24px 0 24px;
        border-radius: 4px;
    }
    .content {
        height: 100%;
        background-color: #fff;
        border-radius: 4px;
        margin-top: 16px;
    }
    .table-box:deep(.@{ant-prefix}-table-thead) > tr > th {
        background-color: #ebf1ff;
        color: #262626;
        font-weight: 600;
        padding: 8px 16px;
        border-right: 1px solid #d9d9d9 !important;
        position: relative;
    }

    .table-box :deep(.@{ant-prefix}-table-tbody) tr > td {
        font-size: 14px;
        font-family: arial, helvetica, 'microsoft yahei';
        font-weight: 400;
        color: #262626;
        border-bottom: 1px solid #d9d9d9;
        padding: 0;
        word-break: break-all;
    }
    .table-box
        :deep(
            .ant3-table.ant3-table-bordered
                > .ant3-table-container
                > .ant3-table-content
                > table
                > thead
                > tr:not(:last-child)
                > th
        ) {
        border-bottom: 1px solid #d9d9d9;
    }
    .table-box-record:deep(.@{ant-prefix}-table-thead) > tr > th {
        background-color: #ebf1ff;
        color: #262626;
        font-weight: 600;
        padding: 8px 16px;
        border-right: 1px solid #d9d9d9 !important;
        position: relative;
    }

    .table-box-record :deep(.@{ant-prefix}-table-tbody) tr > td {
        font-size: 14px;
        font-weight: 400;
        color: #262626;
        padding: 0;
        word-break: break-all;
    }
    .content {
        padding: 16px 24px;
    }
    .opration-text {
        font-size: 14px;
        color: #3875ff;
        font-weight: 500;
        text-decoration: underline;
        cursor: pointer;
    }
    .modal-top {
        display: flex;
        justify-content: end;
        margin-bottom: 16px;
    }
    .modal-top :deep(.ant3-radio-button-wrapper-checked) {
        background: rgba(56, 117, 255, 0.1);
        border: 1px solid #3875ff;
    }
    .modal-top :deep(.ant3-radio-group) {
        border-radius: 0 4px 4px 0;
    }
    .form-div :deep(.ant3-form-item-label) {
        width: 100px;
    }
    .table-top {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 16px;
    }
    .top-right {
        display: flex;
        gap: 16px;
    }
    .color-item {
        display: flex;
        gap: 8px;
        align-items: center;
        font-size: 14px;
        color: #262626;
        letter-spacing: 0;
        font-weight: 400;
    }
    .doing {
        width: 30px;
        height: 12px;
        background: #ffe699;
    }
    .to-do {
        width: 30px;
        height: 12px;
        background: #95de64;
    }
    .to-do-daily {
        width: 30px;
        height: 12px;
        background: #ff7875;
    }
    .factory-div {
        width: 100%;
        height: 20px;
    }
    .reset-btn {
        color: #262626;
        background-color: #eeeeee;
        border-color: #eeeeee;
        border-radius: 4px;
    }
    .reset-btn:hover {
        background: #3875ff;
        border-color: #d9d9d9;
        color: #fff;
    }
    /* 每个日期单元格显示两条状态条 */
    .cell-progress {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        height: 36px;
        width: 100%;
        position: relative;
        padding: 2px 0;
    }

    /* 上面的计划条 */
    .plan-bar {
        height: 40%;
        background-color: #ffec99; /* 浅黄色 */
        margin-bottom: 2px;
    }

    /* 下面的实际条 */
    .actual-bar {
        height: 40%;
    }

    /* 正常完成（绿色） */
    .actual-normal {
        background-color: #95de64;
    }

    /* 延期完成（红色） */
    .actual-delayed {
        background-color: #ff7875;
    }
    .tip-title {
        font-size: 14px;
        border-left: 4px solid #3875ff;
        padding-left: 4px;
        height: 14px;
        line-height: 14px;
        font-weight: 600;
    }
    .table-box
        :deep(.ant3-table.ant3-table-bordered > .ant3-table-container > .ant3-table-content > table > thead > tr > th) {
        font-size: 14px;
        font-weight: 400;
        color: #262626;
        padding: 0 !important;

        .word-wrap {
            word-break: break-all !important;
        }
    }
    .table-box:deep(
            .ant3-table.ant3-table-bordered > .ant3-table-container > .ant3-table-body > table > tbody > tr > td
        ) {
        padding: 0;
    }
    .cell-bar-wrapper {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        height: 39px;
        padding: 2px 0;
    }
    .bar {
        height: 18px;
        width: 100%;
    }
    .gantt-container {
        border: 1px solid #ddd;
    }

    /* 自定义计划条颜色 */
    :deep(.gantt_task_line) {
        &.plan-task {
            border: none;
            background: #ffe699;
        }
        &.none-status {
            display: none;
        }
        &.actual-task {
            border: none;
            background: transparent;
        }
    }
    :deep(.normal-cell) {
        background-color: #95de64 !important;
        border: none;
    }
    :deep(.delayed-cell) {
        background-color: #ef5350 !important;
        border: none;
    }
    :deep(.gantt_grid_scale) {
        background-color: #f2f6fc;
        font-size: 14px;
        color: #333333;
    }
    :deep(.gantt_grid_head_cell) {
        font-size: 14px;
        color: #333333;
    }
    :deep(.gantt_task_scale) {
        background-color: #f2f6fc;
    }
    :deep(.gantt_scale_cell) {
        font-size: 14px;
        color: #333333;
    }
    /* 修改甘特图表头字体颜色 */
    :deep(.gantt_task .gantt_task_scale .gantt_scale_cell) {
        font-size: 14px;
        color: #333333;
    }
    :deep(.cell-ellipsis) {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        display: block;
        cursor: pointer;
        text-align: center;
    }
    /*单数双数鼠标移入颜色*/
    :deep(.gantt_grid_data .gantt_row.odd:hover, .gantt_grid_data .gantt_row:hover) {
        background-color: #f0f8ff; /* 单数行 hover */
    }
    :deep(.gantt_grid_data .gantt_row:hover) {
        background-color: #f0f8ff; /* 偶数行 hover */
    }
    /*选中颜色*/
    :deep(.gantt_task_row.gantt_selected) {
        background-color: #cce5ff !important;
    }
    :deep(
            .gantt_grid_data .gantt_row.gantt_selected,
            .gantt_grid_data .gantt_row.odd.gantt_selected,
            .gantt_task_row.gantt_selected
        ) {
        background-color: #cce5ff !important;
    }
    :deep(.gantt_task_row.gantt_selected .gantt_task_cell) {
        border-right-color: #f0f8ff;
    }
    /* 滚动条样式美化 */
    :deep(.gantt_ver_scroll)::-webkit-scrollbar {
        width: 8px !important;
        height: 15px !important;
    }

    :deep(.gantt_ver_scroll)::-webkit-scrollbar-thumb {
        background: #e8edf3 !important;
        border-radius: 4px !important;
    }

    :deep(.gantt_ver_scroll)::-webkit-scrollbar-thumb:hover {
        background: #e8edf3 !important;
    }
    :deep(.gantt_hor_scroll)::-webkit-scrollbar {
        width: 8px !important;
        height: 8px !important;
    }

    :deep(.gantt_hor_scroll)::-webkit-scrollbar-thumb {
        background: #e8edf3 !important;
        border-radius: 4px !important;
    }

    :deep(.gantt_hor_scroll)::-webkit-scrollbar-thumb:hover {
        background: #e8edf3 !important;
    }
    .gantt-container {
        border: 2px solid #f2f6fc;
    }
    :deep(.gantt_container) {
        border: 3px solid #f2f6fc;
    }
    :deep(.gantt_file) {
        display: none;
    }
    :deep(.gantt_folder_open) {
        display: none;
    }
    :deep(.gantt_folder_closed) {
        display: none;
    }
</style>
